/*
 * SubtreeFilterComponent.java
 *
 * Created on April 29, 2005, 8:09 AM
 */

package org.infoset.xml.filter;


import java.util.*;
import java.io.*;

import org.infoset.xml.*;
import org.infoset.xml.util.DocumentDestination;

/*
 *
 * @author R. Alexander Milowski
 */
public abstract class SubtreeFilter implements ItemFilter
{
   
   protected Name [] names;
   DocumentDestination docDest;
   int level;
   protected ItemDestination output;
  
   public SubtreeFilter()
   {
      names = null;
   }
   
   public SubtreeFilter(Name [] nameList)
   {
      names = nameList;
   }
   
   public void addSubtreeName(Name name) {
      if (names==null) {
         names = new Name[1];
      } else {
         Name [] newnames = new Name[names.length+1];
         System.arraycopy(names,0, newnames,0,names.length);
         names = newnames;
      }
      names[names.length-1] = name;
   }
  
   public void setSubtreeNames(Name [] nameList) {
      names = new Name[nameList.length];
      System.arraycopy(nameList,0, names,0,names.length);
   }
  
   public void send(Item item) 
      throws XMLException
   {
      if (item.getType()==Item.ItemType.DocumentItem) {
         level = -1;
      }
         
      if (level<0) {
         if (item.getType()==Item.ItemType.ElementItem) {
            Element e = (Element)item;
            Name name = e.getName();
            boolean found = false;
            for (int i=0; !found && names!=null && i<names.length; i++) {
               found = names[i].equals(name);
            }
            if (found) {
               docDest = new DocumentDestination();
               docDest.send(item);
               level = 0;
            } else {
               post(item);
            }
         } else {
            post(item);
         }
      } else {
         switch (item.getType()) {
            case ElementItem:
               level++;
               break;
            case ElementEndItem:
               level--;
         }
         docDest.send(item);
         if (level<0) {
            process(docDest.getDocument());
            docDest = null;
         }
      }
   }
   
   public void attach(ItemDestination output) 
      throws XMLException
   {
      this.output = output;
   }
   
   protected void post(Item item) 
      throws XMLException
   {
      if (output==null) {
         return;
      }
      output.send(item);
   }
   
   public abstract void process(Document document) 
      throws XMLException;
   
}
